#include <iostream>
#include <string>
#include <cstring>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include "TaskType.h"

using namespace std;

// 1. 强制1字节对齐（关键！避免结构体多占内存，确保4+4格式）
#pragma pack(1)
struct TLV {
    unsigned int type;    // 4字节（和服务端一致）
    unsigned int length;  // 4字节（和服务端一致）
    char value[1024];     // 数据区（最大1024字节，足够用）
};
#pragma pack()  // 恢复默认对齐

// 2. 打包TLV（严格按4+4+length）
void tlv_pack(TLV& tlv, unsigned int type, const string& data) {
    tlv.type = htonl(type);        // 4字节转网络序
    tlv.length = htonl(data.size());// 4字节转网络序（数据实际长度）
    memset(tlv.value, 0, sizeof(tlv.value));  // 清空数据区，避免脏数据
    if (data.size() > 0) {
        strncpy(tlv.value, data.c_str(), data.size());  // 只复制实际数据
    }
}

// 3. 解包TLV（和服务端解析逻辑对应）
void tlv_unpack(TLV& tlv) {
    tlv.type = ntohl(tlv.type);    // 4字节转主机序
    tlv.length = ntohl(tlv.length);// 4字节转主机序
}

// 4. 建立连接（不变，确保能连到服务端）
int connectToServer(const string& ip, short port) {
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("socket创建失败");
        return -1;
    }

    struct sockaddr_in serverAddr;
    memset(&serverAddr, 0, sizeof(serverAddr));
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(port);
    serverAddr.sin_addr.s_addr = inet_addr(ip.c_str());

    if (connect(sockfd, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == -1) {
        perror("连接服务器失败");
        close(sockfd);
        return -1;
    }

    cout << "已连接到服务器 " << ip << ":" << port << endl;
    return sockfd;
}

// 5. 发送TLV（核心修复：只发送“4+4+实际数据长度”，不发送多余内存）
bool sendTLV(int sockfd, unsigned int type, const string& data) {
    TLV tlv;
    tlv_pack(tlv, type, data);

    // 计算总发送长度：4（type）+4（length）+ 数据实际长度（tlv.length是网络序，先转主机序）
    int total_len = 8 + ntohl(tlv.length);
    // 重点：只发送total_len字节，避免发送value数组的多余空内存
    ssize_t send_len = send(sockfd, &tlv, total_len, 0);
    if (send_len == -1) {
        perror("发送数据失败");
        return false;
    } else if (send_len != total_len) {
        cout << "发送数据不完整（实际发送" << send_len << "字节，需发送" << total_len << "字节）" << endl;
        return false;
    }

    cout << "发送成功：type=" << type << "，数据长度=" << data.size() << "字节" << endl;
    return true;
}

// 6. 接收TLV（和服务端发送逻辑对应）
bool recvTLV(int sockfd, TLV& tlv) {
    // 先接收8字节头部（4+4）
    ssize_t recv_len = recv(sockfd, &tlv, 8, 0);
    if (recv_len == -1) {
        perror("接收头部失败");
        return false;
    } else if (recv_len < 8) {
        cout << "接收头部不完整（只收到" << recv_len << "字节，需8字节）" << endl;
        return false;
    }

    // 解包头部，获取数据长度
    tlv_unpack(tlv);
    // 再接收数据部分（如果有数据）
    if (tlv.length > 0 && tlv.length <= 1024) {
        recv_len = recv(sockfd, tlv.value, tlv.length, 0);
        if (recv_len == -1) {
            perror("接收数据失败");
            return false;
        } else if (recv_len != (ssize_t)tlv.length) {
            cout << "接收数据不完整（只收到" << recv_len << "字节，需" << tlv.length << "字节）" << endl;
            return false;
        }
    }

    cout << "接收成功：type=" << tlv.type << "，数据长度=" << tlv.length << "字节" << endl;
    return true;
}


// 注册流程
void registerProcess(int sockfd) 
{
    string username="www", password="123456";


    // 第一步：发送用户名
    if (!sendTLV(sockfd, TASK_TYPE_REGISTER_SECTION1, username)) 
    {
        return;
    }

    // 接收响应的盐值
    TLV resp1;
    if (!recvTLV(sockfd, resp1)) 
    {
        return;
    }
    cout<<"收到盐值之前"<<endl;
    if (resp1.type == TASK_TYPE_REGISTER_SECTION1_RESP_ERROR) 
    {
        cout << "注册第一步失败: " << resp1.value << endl;
        return;
    }
    string salt = resp1.value;
    cout << "收到盐值: " << salt << endl;

    // 第二步：发送密文
    string encrypted2=crypt(password.c_str(), salt.c_str());

    cout << "生成密文 :" << encrypted2 << endl;

    if (!sendTLV(sockfd, TASK_TYPE_REGISTER_SECTION2, encrypted2)) 
    {
        return;
    }
    // 接收注册结果
    TLV resp2;
    if (!recvTLV(sockfd, resp2)) 
    {
        return;
    }

    if (resp2.type == TASK_TYPE_REGISTER_SECTION2_RESP_OK) {
        cout << "注册成功: " << resp2.value << endl;
    } else {
        cout << "注册失败: " << resp2.value << endl;
    }
}

// 登录流程
void loginProcess(int sockfd) 
{
    string username="www", password="123456";

    cout << " 登录 " << endl;


    // 第一步：发送用户名
    if (!sendTLV(sockfd, TASK_TYPE_LOGIN_SECTION1, username)) {
        return;
    }

    // 接收第一步响应（盐值）
    TLV resp1;
    if (!recvTLV(sockfd, resp1)) {
        return;
    }

    if (resp1.type == TASK_TYPE_LOGIN_SECTION1_RESP_ERROR) 
    {
        cout << "登录第一步失败: " << resp1.value << endl;
        return;
    }
    string salt = resp1.value;
    cout << "收到盐值: " << salt << endl;

    // 第二步：发送密文


    string encrypted1=crypt(password.c_str(), salt.c_str());


    if (!sendTLV(sockfd, TASK_TYPE_LOGIN_SECTION2, encrypted1)) 
    {
        return;
    }

    // 接收登录结果
    TLV resp2;
    if (!recvTLV(sockfd, resp2)) 
    {
        return;
    }

    if (resp2.type == TASK_TYPE_LOGIN_SECTION2_RESP_OK) {
        cout << "登录成功: " << resp2.value << endl;
    } else {
        cout << "登录失败: " << resp2.value << endl;
    }
}

int main(int argc, char* argv[]) 
{


    int sockfd = connectToServer("127.0.0.1", 10086);
    if (sockfd == -1) {
        return -1;
    }


    registerProcess(sockfd);

    sleep(3);
    loginProcess(sockfd);


    close(sockfd);
    return 0;
}